package cn.tj.wenda.cloud.mapper;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.annotation.RegisterMapper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SqlHelper;

@RegisterMapper
public interface CloudUpdateMapper<T> {

    /**
     * 使用主键更新，具有乐观锁校验，更新所有值
     * @param record
     * @return
     */
    @UpdateProvider(type = SQLProvider.class, method = "dynamicSQL")
    int updateByPrimaryKey(T record);

    /**
     * 使用主键更新，具有乐观锁校验，不更新null值
     * @param record
     * @return
     */
    @UpdateProvider(type = SQLProvider.class, method = "dynamicSQL")
    int updateByPrimaryKeySelective(T record);

    /**
     * 使用Example 没有乐观锁校验，更新所有值
     * @param record
     * @param example
     * @return
     */
    @UpdateProvider(type = SQLProvider.class, method = "dynamicSQL")
    int updateByExample(@Param("record") T record, @Param("example") Object example);

    /**
     * 使用Example 没有乐观锁校验，不更新null值
     * @param record
     * @param example
     * @return
     */
    @UpdateProvider(type = SQLProvider.class, method = "dynamicSQL")
    int updateByExampleSelective(@Param("record") T record, @Param("example") Object example);

    class SQLProvider extends MapperTemplate {
        public SQLProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
            super(mapperClass, mapperHelper);
        }

        /**
         * 通过主键更新全部字段
         *
         * @param ms
         */
        public String updateByPrimaryKey(MappedStatement ms) {
            Class<?> entityClass = getEntityClass(ms);
            StringBuilder sql = new StringBuilder();
            sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass)));
            sql.append(SqlHelper.updateSetColumns(entityClass, null, false, false));
            sql.append(CloudSqlHelper.wherePKColumns(entityClass));
            return sql.toString();
        }

        /**
         * 通过主键更新不为null的字段
         *
         * @param ms
         * @return
         */
        public String updateByPrimaryKeySelective(MappedStatement ms) {
            Class<?> entityClass = getEntityClass(ms);
            StringBuilder sql = new StringBuilder();
            sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass)));
            sql.append(SqlHelper.updateSetColumns(entityClass, null, true, isNotEmpty()));
            sql.append(CloudSqlHelper.wherePKColumns(entityClass));
            return sql.toString();
        }

        /**
         * 根据Example更新
         *
         * @param ms
         * @return
         */
        public String updateByExample(MappedStatement ms) {
            Class<?> entityClass = getEntityClass(ms);
            StringBuilder sql = new StringBuilder();
            if (isCheckExampleEntityClass()) {
                sql.append(SqlHelper.exampleCheck(entityClass));
            }
            //安全更新，Example 必须包含条件
            if (getConfig().isSafeUpdate()) {
                sql.append(SqlHelper.exampleHasAtLeastOneCriteriaCheck("example"));
            }
            sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass), "example"));
            sql.append(SqlHelper.updateSetColumns(entityClass, "record", false, false));
            sql.append(CloudSqlHelper.updateByExampleWhereClause());
            return sql.toString();
        }

        /**
         * 根据Example更新非null字段
         *
         * @param ms
         * @return
         */
        public String updateByExampleSelective(MappedStatement ms) {
            Class<?> entityClass = getEntityClass(ms);
            StringBuilder sql = new StringBuilder();
            if (isCheckExampleEntityClass()) {
                sql.append(SqlHelper.exampleCheck(entityClass));
            }
            //安全更新，Example 必须包含条件
            if (getConfig().isSafeUpdate()) {
                sql.append(SqlHelper.exampleHasAtLeastOneCriteriaCheck("example"));
            }
            sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass), "example"));
            sql.append(SqlHelper.updateSetColumns(entityClass, "record", true, isNotEmpty()));
            sql.append(CloudSqlHelper.updateByExampleWhereClause());
            return sql.toString();
        }

    }
}
